<?php
namespace app\mxty\logic;

use think\facade\Cache;
use think\facade\Request;
use app\common\library\wechat\WxPay;
use \DateTime;
use \DateInterval;
use \DateTimeZone;

use app\mxty\model\MemberCard as MemberCardModel;
use app\mxty\model\Coach as CoachModel;
use app\mxty\model\MemberCardOrder as MemberCardOrderModel;
use app\api\model\Wxapp as WxappModel;
use app\api\model\User as UserModel;

use app\api\service\User as UserService;
use app\api\service\passport\Login as LoginService;

use app\common\enum\OrderType as OrderTypeEnum;

class MemberCard
{
    public function getCardDetail($cardId)
    {
        $model = new MemberCardModel();
        $card = $model->getDetail($cardId);
        return $card->toArray();
    }

    public function buyCard($cardId)
    {
        // 获取当前请求的用户信息
        $user = UserService::getCurrentLoginUser(true);
        // 查找对应会员卡信息
        $card = (new MemberCardModel())->getDetail($cardId);
        if ($card->isEmpty()) {
            throwError('会员卡不存在');
        }
        // 创建订单
        $params = [
            'membercard_id' => $card->nid,
            'card_name' => $card->name,
            'user_id' => $user->user_id,
            'order_no' => $this->createOrderNo(),
            'price' => $card->price,
            'introduce' => $card->introduce,
            'use_rules' => $card->use_rules,
            'type' => $card->type,
            'limite' => $card->limite,
            'image_id' => $card->image_id,
            'effective' => $card->effective,
        ];
        $order = MemberCardOrderModel::order($params);
        // 创建微信支付预订单
        $notifyUrl =
            Request::domain() . '/index.php/mxty/payment/buyCardNotify';
        // 统一下单API
        $wxConfig = static::getWxConfig();
        $WxPay = new WxPay($wxConfig);
        $result = $WxPay->unifiedorder(
            $order->order_no,
            $user->open_id,
            $card->price,
            OrderTypeEnum::ORDER,
            $notifyUrl
        );
        return array_merge($result, ['appId' => $wxConfig['app_id']]);
    }

    // 获取指定的会员卡订单信息
    public static function getOrderInfo($order_no)
    {
        $order = MemberCardOrderModel::getInfoByOderNo($order_no);
        return $order;
    }

    public function getUserCards()
    {
        // 获取当前请求的用户信息
        $user = UserService::getCurrentLoginUser(true);
        $list = (new MemberCardOrderModel())->getCardsByUserId($user->user_id);
        foreach ($list as $card) {
            $remaining = $this->getRemainingDay(
                $card->pay_time,
                $card->effective
            );
            $card->remaining_day = $remaining['days'];
            if ($remaining['invert'] == 1) {
                // 已过期
                $card->remaining_day = 0;
            }

            // 如果是有限次数的会员卡，计算会员卡的剩余使用次数
            if ($card->type == 1) {
                $card->remaining_times = $card->limite - $card->used_times;
            }
        }

        return $list->toArray();
    }

    // 获取会员卡的剩余有效天数，根据付款日期 pay_time 和 有效期 effective 计算剩余天数
    public function getRemainingDay($pay_time, $effective)
    {
        $pay_date = new DateTime(null, new DateTimeZone('Asia/shanghai'));
        $pay_date->setTimestamp($pay_time);
        // 购买时间加上有效期，即到期时间
        $effective = (int)$effective + 1;
        $pay_date->add(new DateInterval("P{$effective}D"));

        $now = new DateTime(null, new DateTimeZone('Asia/shanghai'));

        $interval = $now->diff($pay_date);

        return [
            'invert' => $interval->invert,
            'days' => $interval->days,
        ];
    }

    // 工作人员扫码检查会员卡信息
    public function checkCardInfo($orderId, $token)
    {
        // 验证用户和会员卡
        $order = $this->verifyCard($orderId, $token);
        // 获取会员卡的有效信息
        $orderInfo = $this->getValidInfo($order);

        return $orderInfo->toArray();
    }

    /**
     * 获取卡的有效信息
     * @param MemberCardOrderModel $order
     * @return MemberCardOrderModel $order
     * */

    public function getValidInfo($order)
    {
        // 计算会员卡的有效信息
        $remaining = $this->getRemainingDay(
            $order->pay_time,
            $order->effective
        );
        $order->remaining_day = $remaining['days'];
        if ($remaining['invert'] == 1) {
            // 已过期
            $order->remaining_day = 0;
        }

        // 如果是有限次数的会员卡，计算会员卡的剩余使用次数
        if ($order->type == 1) {
            $order->remaining_times = $order->limite - $order->used_times;
        }
        $order->pay_date = date('Y-m-d', $order->pay_time);
        return $order;
    }

    // 验证工作人员和用户的身份，检查会员卡是否存在
    public function verifyCard($orderId, $token)
    {
        // 获取进行扫码操作的用户信息，如果未登陆会提示用户登陆
        $scanCodeUser = UserService::getCurrentLoginUser(true);
        // 验证扫码操作的用户身份，是否为工作人员
        $employee = (new CoachModel())->findEmployeeByUserId(
            $scanCodeUser->user_id
        );
        if ($employee->isEmpty()) {
            throwError('只有工作人员才能进行扫码操作哦');
        }
        // 验证二维码所属的用户的身份
        $user = $this->getUserInfo($token);
        if (!$user) {
            throwError('二维码已使用或已失效，请刷新会员卡二维码后重新扫码');
        }

        // 获取该会员卡的信息
        $order = (new MemberCardOrderModel())->getInfoById(
            $orderId,
            $user->user_id
        );

        if ($order->isEmpty()) {
            throwError('没有找到该会员卡信息');
        }

        return $order;
    }

    // 使用会员卡
    public function useCard($orderId, $token)
    {
        // 验证用户身份和会员卡是否存在
        $order = $this->verifyCard($orderId, $token);
        // 获取会员卡的有效信息
        $orderInfo = $this->getValidInfo($order);

        // 会员卡已过期
        if($orderInfo->remaining_day === 0) {
          throwError('会员卡已过期');
        }

        // 会员卡未过期，且为有限次数卡
        if($orderInfo->remaining_day > 0 && $orderInfo->type == 1) {
          if($orderInfo->remaining_times > 0) {
            // 剩余有效次数大于0，则增加一次使用次数
            $order->useOneTimes();
            // 成功增加使用次数后，删除该二维码token
            Cache::delete($token); 
          }else{
            // 已无剩余有效次数
            throwError('会员卡已无剩余使用次数');
          }
        }

        // 若有有效期内无限次卡
        if($orderInfo->type != 1) {
            // 增加一次使用次数
            $order->useOneTimes();
            // 成功增加使用次数后，删除该二维码token
            Cache::delete($token); 
        }

        return $this->getValidInfo($order)->toArray();
    }

    public function getUserInfo($token)
    {
        // 通过该二维码token获取user_id
        $user_id = Cache::get($token);
        // 获取用户信息
        $user = UserModel::detail($user_id);
        
        return $user;
    }

    // 生成会员卡二维码token
    public function generateCodeToken()
    {
      // 获取当前请求的用户信息
      $user = UserService::getCurrentLoginUser(true);
      $codeToken = (new LoginService)->makeToken($user->user_id);
      // 设置一个5分钟的缓存
      Cache::set($codeToken, $user->user_id, 300);
      return $codeToken;
    }

    /**
     * 获取微信支付配置
     * @return array
     * @throws BaseException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    private static function getWxConfig()
    {
        return WxappModel::getWxappCache(getStoreId());
    }

    /**
     * 生成订单号
     * @return string
     */
    public function createOrderNo()
    {
        return date('Ymd') .
            substr(
                implode(
                    null,
                    array_map('ord', str_split(substr(uniqid(), 7, 13), 1))
                ),
                0,
                10
            );
    }
}
